﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;

#region IMLibrary  
using IMLibrary.IO;
//using IMLibrary.NetClient;
//using Ourmsg.NetClient;
#endregion


namespace Ourmsg.FileTransmit
{
    /// <summary>
    /// 文件传输基础类
    /// </summary>
    public class FileTransmitBaseV1 
    {
        #region 构造
        /// <summary>
        /// 
        /// </summary>
        /// <param name="tFileInfo"></param>
        /// <param name="serverIP"></param>
        /// <param name="Port"></param>
        /// <param name="isSend"></param>
        public FileTransmitBaseV1(TFileInfo tFileInfo, string serverIP, int Port,bool isSend) 
        {
            _IsSend = isSend;
            TFileInfo = tFileInfo;
            TFileInfo.IsSend = IsSend;
            this.ServerIP = serverIP; this.ServerPort = Port;

            if (!isSend)
            {
                ///创建接收文件夹
                System.IO.DirectoryInfo dInfo = new System.IO.DirectoryInfo("ReceivedFile");
                if (!dInfo.Exists)
                    dInfo.Create();
                dInfo = null;

                ///创建接收缓存文件夹
                dInfo = new System.IO.DirectoryInfo("FileCache");
                if (!dInfo.Exists)
                    dInfo.Create();
                dInfo = null;
            } 
        }
        #endregion

        #region 释放资源
        /// <summary>
        /// 释放资源
        /// </summary>
        public virtual void Dispose()
        {
            if (FS != null)//关闭文件流
            {
                FS.Close(); FS.Dispose();
            }
            FS = null; 

            this.TFileInfo = null;
            this.fileBlock = null;
        }
        #endregion
         
        #region 变量 
        /// <summary>
        /// 代理服务器主机信息
        /// </summary>
        protected string  ServerIP = "127.0.0.1";
        /// <summary>
        /// 代理服务器端口
        /// </summary>
        protected int ServerPort = 90;
        /// <summary>
        /// 标记文件是否在传输过程中
        /// </summary>
        protected bool isTransmit = false; 
        /// <summary>
        /// 当前获得文件的数据长度
        /// </summary>
        protected long currGetPos = 0;
        /// <summary>
        /// 传输文件的信息
        /// </summary>
        public TFileInfo TFileInfo = new TFileInfo();
        /// <summary>
        /// 缓冲文件保存位置
        /// </summary>
        protected string CacheFile = "";
        /// <summary>
        /// 文件操作流
        /// </summary>
        protected FileStream FS = null;
        /// <summary>
        /// 当前收到的数据包长度,断点续传的继点记忆
        /// </summary>
        protected int CurrRecLength = 0;
        #endregion

        #region 事件
        /// <summary>
        /// 文件传输结束
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public delegate void  TransmitEventHandler(object sender, fileTransmitEvnetArgs e);

        bool isOver = false;
        /// <summary>
        /// 文件传输结束
        /// </summary>
        public event TransmitEventHandler Transmitted;
        /// <summary>
        /// 触发文件传输结束事件
        /// </summary>
        protected virtual void OnTransmitted()
        {
            if (isOver) return;
            isOver = true;
            if (Transmitted != null)
                Transmitted(this, new fileTransmitEvnetArgs(TFileInfo));
        }


        /// <summary>
        /// 允许断点续传
        /// </summary>
        public event TransmitEventHandler AllowResume;
        /// <summary>
        /// 触发允许文件断点续传事件
        /// </summary>
        protected virtual void OnAllowResume()
        {
            if (AllowResume != null)
               AllowResume(this, new fileTransmitEvnetArgs(TFileInfo));
        }

        /// <summary>
        /// 取消文件传输
        /// </summary>
        public event TransmitEventHandler  Cancel;
        /// <summary>
        /// 触发文件传输取消事件
        /// </summary>
        protected virtual void OnCancel()
        {
            if ( Cancel != null)
               Cancel(this, new fileTransmitEvnetArgs(TFileInfo));
        }

        /// <summary>
        /// 文件传输开始
        /// </summary>
        public event TransmitEventHandler  TransmitBefore;
        /// <summary>
        /// 触发文件传输前事件
        /// </summary>
        protected virtual void OnTransmitBefore()
        {
            if (TransmitBefore != null)
               TransmitBefore(this, new fileTransmitEvnetArgs(TFileInfo));
        }

        /// <summary>
        ///  文件传输超时 
        /// </summary>
        public event TransmitEventHandler TransmitOutTime;
        /// <summary>
        /// 触发文件传输超时事件
        /// </summary>
        protected virtual void OnTransmitOutTime()
        {
            if (TransmitOutTime != null)
               TransmitOutTime(this, new fileTransmitEvnetArgs(TFileInfo));
        }

        /// <summary>
        /// 文件传输错误事件
        /// </summary>
        public event TransmitEventHandler TransmitError;
        /// <summary>
        /// 触发文件传输错误事件
        /// </summary>
        protected virtual void OnTransmitError()
        {
            if (TransmitError != null)
                TransmitError(this, new fileTransmitEvnetArgs(TFileInfo));
        }

        /// <summary>
        /// 事件：发送或收到文件数据
        /// </summary>
        public event TransmitEventHandler Transmitting;
        /// <summary>
        /// 触发文件传输中事件
        /// </summary>
        protected virtual void OnTransmitting()
        {
            if (Transmitting != null)
              Transmitting(this, new fileTransmitEvnetArgs(TFileInfo));
        }

        bool isConneted = false;//标记是否已经触发过事件
        /// <summary>
        /// 文件传输成功联接到服务器事件
        /// </summary>
        public event TransmitEventHandler Connected;
        /// <summary>
        /// 触发文件传输成功联接到服务器事件
        /// </summary>
        protected virtual void OnConnected()
        {
            if (isConneted) return;
            isConneted = true;
            if (Connected != null)
                Connected(this, new fileTransmitEvnetArgs(TFileInfo));
        }

        /// <summary>
        /// 网络中断事件
        /// </summary>
        public event TransmitEventHandler  Disconnected;
        /// <summary>
        /// 触发网络中断事件 
        /// </summary>
        protected virtual void OnDisconnected()
        {
            if (Disconnected != null)
                Disconnected(this, new fileTransmitEvnetArgs(TFileInfo));
        }


        /// <summary>
        /// 连接UDP服务器失败事件
        /// </summary>
        public event TransmitEventHandler ConnecteUDPServerFailed;
        /// <summary>
        /// 触发连接UDP服务器失败事件
        /// </summary>
        protected virtual void OnConnecteUDPServerFailed()
        {
            if (ConnecteUDPServerFailed != null)
                ConnecteUDPServerFailed(this, new fileTransmitEvnetArgs(TFileInfo));
        }
        #endregion

        #region 属性
        /// <summary>
        /// 每次发送的数据包缓冲容量
        /// </summary>
        protected int mtu  //标记一次传输文件数据块的大小，不能超过网络最大传输单元 MTU 576-1492 限制，否则在因特网上的数据发送将不成功
        {
            set { buffer = new byte[value]; }
            get { return buffer.Length; }
        }

        /// <summary>
        /// 要发送的缓冲区
        /// </summary>
        protected byte[] buffer = new byte[0];

        
        /// <summary>
        ///  一次读写文件的缓冲区大小 
        /// </summary>
        protected byte[] fileBlock = null ;

        private int _maxReadWriteFileBlock = 1024000;//一次读写文件的大小1M
        /// <summary>
        /// 一次读写文件的大小
        /// </summary>
        public int maxReadWriteFileBlock
        {
            set { _maxReadWriteFileBlock = value ; }
            get { return _maxReadWriteFileBlock; }
        }


        private int outTime = 3;
        /// <summary>
        /// 超时秒数
        /// </summary>
        public int OutTime
        {
            set { outTime = value; }
            get { return outTime; }
        }

         bool _IsSend = false;
        /// <summary>
        /// 标记本机是发送端还是接收端
        /// </summary>
        public bool IsSend
        {
            get {return  _IsSend; }
        }
        #endregion

        #region 方法

        #region 判断当前是否需要读写文件
        /// <summary>
        /// 判断当前是否需要读写文件
        /// </summary>
        /// <returns></returns>
        protected bool IsReadWriteFile()
        {
            if (CurrRecLength  % maxReadWriteFileBlock == 0)
                return true;
            else
                return false;
        }
        #endregion

        #region 关闭文件流
        /// <summary>
        /// 关闭文件流
        /// </summary>
        protected void CloseFileStream()
        {
            if (FS != null)
            { FS.Close(); FS.Dispose(); FS = null; }
        }
        #endregion

        #endregion
    }
}
